home *** CD-ROM | disk | FTP | other *** search
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/resident.h>
- #include <exec/errors.h>
- #include <libraries/expansionbase.h>
- #include <libraries/configvars.h>
- #include <devices/trackdisk.h>
-
- /*
- * Set SysBase to a local variable, that loads directly from 4 when it
- * has to be reloaded
- */
- #define BASE_EXT_DECL
- #define BASE_NAME (*(void **)4)
- #include <inline/exec.h>
-
- #include "device.h"
-
- /*
- * Unit task. First figures out, of which type it is, then waits for
- * command requests from BeginIO.
- */
-
- DECL_DPRINTF;
- extern struct MsgPort *CreatePort(char *name, int pri);
-
- extern int (*cmd_table[]) ();
-
- /* this is a unit task */
-
- void
- unit_start (struct scsi_unit *su)
- {
- struct scsi_msg *sm = &su->scu_hmessage;
- struct SCSICmd *cmd;
- struct IOStdReq *io_req;
- ubyte *cb;
- ulong inq_buf;
- ulong sense_buf;
- struct MsgPort *mp;
- int retries;
-
- DPRINTF(("unit-task: %ld started", su->scu_unitnum));
-
- mp = &su->scu_unit.unit_MsgPort;
- mp->mp_Node.ln_Type = NT_MSGPORT;
- mp->mp_SigBit = AllocSignal(-1);
- mp->mp_SigTask = FindTask(0);
- mp->mp_Flags = PA_SIGNAL;
- NewList(&mp->mp_MsgList);
-
- sm->scm_message.mn_ReplyPort = mp;
-
- su->scu_cmd_mp = CreatePort(0,0);
- su->scu_errors = su->scu_errorlevel = 0;
-
- sm->scm_unit = su->scu_unitnum;
- cmd = &su->scu_scsicmd;
-
- sm->scm_scsi_cmd = cmd;
- cmd->scsi_Command = cb = su->scu_cmd;
-
- /* first find out, what kind this device is of */
- cb[0] = 0x12; /* INQUIRY */
- cb[1] = cb[2] = cb[3] = 0;
- cb[4] = 2; /* allocation length */
- cb[5] = 0;
- cmd->scsi_Data = (UWORD *)&inq_buf;
- cmd->scsi_Length = 2;
- cmd->scsi_Flags = SCSIF_READ|SCSIF_OLDAUTOSENSE;
- cmd->scsi_SenseData = (UBYTE *)&sense_buf;
- cmd->scsi_SenseLength = 4;
- retries = 60;
-
- /* account for UNIT ATTENTION sense response */
- do
- {
- sm->scm_cmd = SCM_CMD_EXEC_SCSI;
-
- PutGetMsg(su->scu_hmsgport, &su->scu_unit.unit_MsgPort,
- (struct Message *)sm);
- }
- /* as long as the device responds UNIT_ATTENTION */
- while (((sm->scm_cmd == HFERR_BadStatus && sense_buf == 0x07000600)
- || (sm->scm_cmd > HFERR_BadStatus)) && retries-- > 0);
-
- DPRINTF(("identified unit %ld, result = %ld, inq_buf = $%lx, sense = $%lx",
- su->scu_unitnum, sm->scm_cmd, inq_buf, sense_buf));
-
- if (sm->scm_cmd == 0) /* scm_cmd is io_Error when returned */
- {
- su->scu_type = inq_buf >> 24;
- if (inq_buf & 0x00800000) su->scu_type |= SCU_TYPE_RMB;
- }
- else
- {
- /* in that case assume a non removable DIRECT ACCESS device... */
- su->scu_type = SCU_TYPE_DIRECT;
- }
-
- /* START/STOP unit on sequential devices means LOAD/UNLOAD, since
- * we can't garantee that there's a tape inserted, this command might
- * always fail... so better don't issue it */
-
- if ((su->scu_type & ~SCU_TYPE_RMB) == SCU_TYPE_DIRECT)
- {
- cb[0] = 0x1b; /* START/STOP UNIT */
- cb[1] = 0; /* not immed, return, when unit really ready */
- cb[2] = cb[3] = 0;
- cb[4] = 1; /* start unit */
- cb[5] = 0;
- cmd->scsi_Data = 0;
- cmd->scsi_Length = 0;
-
- for (retries = 0; retries < 60; retries ++)
- {
- sm->scm_cmd = SCM_CMD_EXEC_SCSI;
-
- PutGetMsg(su->scu_hmsgport, &su->scu_unit.unit_MsgPort,
- (struct Message *)sm);
- if (sm->scm_cmd == 0) break;
- }
-
- DPRINTF(("unit %ld, start_unit returned %ld, retry = %ld",
- su->scu_unitnum, sm->scm_cmd, retries));
- }
-
- /* now set block length.. this is important for streamers or other
- * devices that may support different block lengths */
- if ((su->scu_type & ~SCU_TYPE_RMB) == SCU_TYPE_DIRECT)
- {
- cb[0] = 0x15; /* MODE_SELECT */
- cb[1] = 1; /* save parameters */
- cb[2] = cb[3] = 0;
- cb[4] = 12; /* parameter list length */
- cb[5] = 0;
- /* this is the actual parameter list, that switches the device into
- * 512 byte block mode */
- su->scu_buf[0] =
- su->scu_buf[1] =
- su->scu_buf[2] = 0;
- su->scu_buf[3] = 8;
- su->scu_buf[4] =
- su->scu_buf[5] =
- su->scu_buf[6] =
- su->scu_buf[7] =
- su->scu_buf[8] =
- su->scu_buf[9] = 0;
- su->scu_buf[10] = 2; /* 0x200 = 512 */
- su->scu_buf[11] = 0;
- }
- else /* SCU_TYPE_SEQUENTIAL */
- {
- cb[0] = 0x15; /* MODE_SELECT */
- cb[1] = 0; /* reserved */
- cb[2] = cb[3] = 0;
- cb[4] = 12; /* parameter list length */
- cb[5] = 0;
- /* this is the actual parameter list, that switches the device into
- * 512 byte block mode */
- su->scu_buf[0] =
- su->scu_buf[1] = 0; /* reserved */
- su->scu_buf[2] = 0x10; /* buffered writes ok, default speed */
- su->scu_buf[3] = 8;
- su->scu_buf[4] = /* default density */
- su->scu_buf[5] =
- su->scu_buf[6] =
- su->scu_buf[7] =
- su->scu_buf[8] =
- su->scu_buf[9] = 0;
- su->scu_buf[10] = 2; /* 0x200 = 512 */
- su->scu_buf[11] = 0;
- }
-
- cmd->scsi_Data = (UWORD *)su->scu_buf;
- cmd->scsi_Flags = SCSIF_OLDAUTOSENSE; /* no READ, this is a write ! */
- cmd->scsi_Length = 12;
-
- for (retries = 0; retries < 60; retries ++)
- {
- sm->scm_cmd = SCM_CMD_EXEC_SCSI;
-
- PutGetMsg(su->scu_hmsgport, &su->scu_unit.unit_MsgPort,
- (struct Message *)sm);
- if (sm->scm_cmd == 0) break;
- }
-
- DPRINTF(("unit %ld, mode_select returned %ld, retry = %ld",
- su->scu_unitnum, sm->scm_cmd, retries));
-
-
- /* reading the first cylinder, until we don't get any errors, seems
- * a good way to ensure, that the unit is working.. well, hddisk
- * does it that way... */
-
- if ((su->scu_type & ~SCU_TYPE_RMB) == SCU_TYPE_DIRECT)
- {
- cb[0] = 0x8; /* READ */
- cb[1] = cb[2] = cb[3] = 0;
- cb[4] = 1; /* allocation length (1 Block)*/
- cb[5] = 0;
- cmd->scsi_Length = 512;
- cmd->scsi_Data = (UWORD *)su->scu_buf;
- cmd->scsi_Flags = SCSIF_READ|SCSIF_OLDAUTOSENSE;
-
- for (retries = 0; retries < 60; retries ++)
- {
- sm->scm_cmd = SCM_CMD_EXEC_SCSI;
-
- PutGetMsg(su->scu_hmsgport, &su->scu_unit.unit_MsgPort,
- (struct Message *)sm);
- if (sm->scm_cmd == 0) break;
- }
- }
-
- /* for now, DON'T mount the disk.. we can do this manually, and this
- * garantees yet another source of bugs we can eliminate during the
- * testing phase.. */
-
- DPRINTF(("unit %ld ready, type $%lx, (retries = %ld), awaiting commands",
- su->scu_unitnum, su->scu_type, retries));
-
- #ifdef ENABLE_CACHE
- invalidate_cache (su);
- #endif
-
- for (;;)
- {
- WaitPort(su->scu_cmd_mp);
- while (io_req = (struct IOStdReq *)GetMsg(su->scu_cmd_mp))
- {
- DPRINTF(("unit %ld (%ld), command %ld",
- su->scu_unitnum, ((struct scsi_unit*)io_req->io_Unit)->scu_unitnum,
- io_req->io_Command));
-
- /* beginio already validated the io_Command field */
- io_req->io_Error = (*cmd_table[io_req->io_Command])(io_req);
- ReplyMsg((struct Message *)io_req);
- }
- }
- }
-